﻿using System;

namespace FBGraph
{
    /// <summary>Encapsulates paging options for requests that return a <see cref="PagedResult{TModel}" /> type.</summary>
    public struct PagingOptions
    {
        /// <summary>Gets or sets the upper bound of the date filter.</summary>
        public DateTime? FetchUntil { get; set; }

        /// <summary>Gets or sets the lower bound of the date filter.</summary>
        public DateTime? FetchSince { get; set; }

        /// <summary>Gets or sets the maximum number of results that should be retuned.</summary>
        public Int32? LimitCount { get; set; }

        /// <summary>Gets or sets the index offset from which to start returning results.</summary>
        public Int32? OffsetIndex { get; set; }

        /// <summary>Gets an instance of <see cref="PagingOptions" /> with <see cref="FetchUntil" /> set to <paramref name="until" />.</summary>
        /// <param name="until">A <see cref="DateTime" /> that will be the upper bound of the date filter.</param>
        /// <returns>An instance of <see cref="PagingOptions" /> with <see cref="FetchUntil" /> set to <paramref name="until" />.</returns>
        public static PagingOptions Until(DateTime until) { return new PagingOptions { FetchUntil = until }; }

        /// <summary>Gets an instance of <see cref="PagingOptions" /> with <see cref="FetchSince" /> set to <paramref name="since" />.</summary>
        /// <param name="since">A <see cref="DateTime" /> that will be the lower bound of the date filter.</param>
        /// <returns>An instance of <see cref="PagingOptions" /> with <see cref="FetchSince" /> set to <paramref name="since" />.</returns>
        public static PagingOptions Since(DateTime since) { return new PagingOptions { FetchSince = since }; }

        /// <summary>Gets an instance of <see cref="PagingOptions" /> with <see cref="LimitCount" /> set to <paramref name="limit" />.</summary>
        /// <param name="limit">An <see cref="Int32" /> value that will be the maximum number of results.</param>
        /// <returns>An instance of <see cref="PagingOptions" /> with <see cref="LimitCount" /> set to <paramref name="limit" />.</returns>
        public static PagingOptions Limit(Int32 limit) { return new PagingOptions { LimitCount = limit }; }

        /// <summary>Gets an instance of <see cref="PagingOptions" /> with <see cref="OffsetIndex" /> set to <paramref name="offset" />.</summary>
        /// <param name="offset">An <see cref="Int32" /> value that will be the offset from which to start returning results.</param>
        /// <returns>An instance of <see cref="PagingOptions" /> with <see cref="OffsetIndex" /> set to <paramref name="offset" />.</returns>
        public static PagingOptions Offset(Int32 offset) { return new PagingOptions { OffsetIndex = offset }; }
    }

    /// <summary>Contains extensions for the <see cref="PagingOptions" /> struct.</summary>
    public static class PagingOptionsExtensions
    {
        /// <summary>Sets the <see cref="PagingOptions.FetchUntil" /> property.</summary>
        /// <param name="pagingOptions">A <see cref="PagingOptions" /> value.</param>
        /// <param name="until">A <see cref="DateTime" /> that will be the upper bound of the date filter.</param>
        /// <returns>The <see cref="PagingOptions" /> value with the <see cref="PagingOptions.FetchUntil" /> property set to <paramref name="until" />.</returns>
        public static PagingOptions Until(this PagingOptions pagingOptions, DateTime until)
        {
            pagingOptions.FetchUntil = until;
            return pagingOptions;
        }

        /// <summary>Sets the <see cref="PagingOptions.FetchSince" /> property.</summary>
        /// <param name="pagingOptions">A <see cref="PagingOptions" /> value.</param>
        /// <param name="since">A <see cref="DateTime" /> that will be the lower bound of the date filter.</param>
        /// <returns>The <see cref="PagingOptions" /> value with the <see cref="PagingOptions.FetchSince" /> property set to <paramref name="since" />.</returns>
        public static PagingOptions Since(this PagingOptions pagingOptions, DateTime since)
        {
            pagingOptions.FetchSince = since;
            return pagingOptions;
        }

        /// <summary>Sets the <see cref="PagingOptions.LimitCount" /> property.</summary>
        /// <param name="pagingOptions">A <see cref="PagingOptions" /> value.</param>
        /// <param name="limit">An <see cref="Int32" /> value that will be the maximum number of results.</param>
        /// <returns>The <see cref="PagingOptions" /> value with the <see cref="PagingOptions.LimitCount" /> property set to <paramref name="until" />.</returns>
        public static PagingOptions Limit(this PagingOptions pagingOptions, Int32 limit)
        {
            pagingOptions.LimitCount = limit;
            return pagingOptions;
        }

        /// <summary>Sets the <see cref="PagingOptions.OffsetIndex" /> property.</summary>
        /// <param name="pagingOptions">A <see cref="PagingOptions" /> value.</param>
        /// <param name="offset">An <see cref="Int32" /> value that will be the offset from which to start returning results.</param>
        /// <returns>The <see cref="PagingOptions" /> value with the <see cref="PagingOptions.OffsetIndex" /> property set to <paramref name="offset" />.</returns>
        public static PagingOptions Offset(this PagingOptions pagingOptions, Int32 offset)
        {
            pagingOptions.OffsetIndex = offset;
            return pagingOptions;
        }
    }
}